package com.jianguozh.difs.framework.validator;

import lombok.SneakyThrows;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.annotation.Resource;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 唯一值校验器
 *
 * @author hanrs
 * @email 40736130@qq.com
 * @since 2022/4/23 3:28 PM
 */
public class UniqueValidator implements ConstraintValidator<UniqueValid, Object> {

    @SneakyThrows
    @Override
    public boolean isValid(Object obj, ConstraintValidatorContext context) {
        Class<?> aClass = obj.getClass();
        Field[] fields = aClass.getDeclaredFields();
        // 用户提交的id
        String id = null;
        // 唯一约束列名和值
        Map<String, Object> uniqueColumnsMap = new HashMap<>(3);

        // 获取用户提交的id值, 唯一约束字段名及值
        for (Field field : fields) {
            field.setAccessible(true);
            String fieldName = field.getName();
            if ("id".equals(fieldName)) {
                id = (String)field.get(obj);
            }
            for (String column : columns) {
                if (Objects.equals(column, fieldName)) {
                    uniqueColumnsMap.put(camel2Underline(column), field.get(obj));
                }
            }
        }

        // 检查唯一约束字段是否重复
        boolean isUnique = false;
        for (String column : uniqueColumnsMap.keySet()) {
            // 查询sql select id from tableName where column='value' limit 1
            String sb = "select id from " + tableName + " where " + column + "=" + "'" + uniqueColumnsMap.get(column) + "'" + " limit 1";
            List<String> dbIds = jdbcTemplate.queryForList(sb, String.class);
            // 如果数据库的id和用户提交的id相等则认为该字段唯一
            if (dbIds.isEmpty() || Objects.equals(dbIds.get(0), id) || Objects.equals(id, null)) {
                isUnique = true;
            }else {
                isUnique = false;
                break;
            }
        }
        // 主观认为用户输入的都是不唯一的
        return isUnique;
    }

    @Override
    public void initialize(UniqueValid unique) {
        this.tableName = unique.tableName();
        this.columns = unique.columns();
    }

    /**
     * 驼峰转下划线
     *
     * @param str
     * @return
     */
    public String camel2Underline(String str) {
        if (str == null || str.trim().isEmpty()){
            return "";
        }
        int len = str.length();
        StringBuilder sb = new StringBuilder(len);
        sb.append(str.substring(0, 1).toLowerCase());
        for (int i = 1; i < len; i++) {
            char c = str.charAt(i);
            if (Character.isUpperCase(c)) {
                sb.append("_");
                sb.append(Character.toLowerCase(c));
            } else {
                sb.append(c);
            }
        }
        return sb.toString();
    }


    /**
     * 实体对应的表名
     */
    private String tableName;
    /**
     * 唯一字段列名(数据库字段名)
     */
    private String[] columns;
    /**
     * jdbcTemplate
     */
    @Resource
    private JdbcTemplate jdbcTemplate;

}
